import cal3d

Class CalRenderer

	Field m_model:CalModel
	Field m_selectedSubmesh:CalSubmesh
	
	Method New()
		m_model = Null
		m_selectedSubmesh = Null
	End
	
	Method New(model:CalModel)
		m_model = model
	End
	
	Method New(renderer:CalRenderer)
		m_model = renderer.m_model
		m_selectedSubmesh = renderer.m_selectedSubmesh
	End
	
	Method beginRendering:Bool()
		' get the attached meshes vector
		Local vectorMesh:CalMesh[] = m_model.getVectorMesh()
	
		' check if there are any meshes attached to the model
		If vectorMesh.Length = 0 then
			Return False
		Endif
	
		' select the default submesh
		m_selectedSubmesh = vectorMesh[0].getSubmesh(0)
		If m_selectedSubmesh = Null Then
			Return False
		Endif
		Return True		
	End
	
	Method endRendering:Void()
		m_selectedSubmesh = Null
	End

	Method getAmbientColor:Void(colorBuffer:Float[])
	
		' get the core material
		Local coreMaterial:CalCoreMaterial = this.m_model.getCoreModel().getCoreMaterial(this.m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null then
			' write default values to the color buffer
			colorBuffer[0] = 0
			colorBuffer[1] = 0
			colorBuffer[2] = 0
			colorBuffer[3] = 0
	
			return
		Endif
	
		' get the ambient color of the material
		Local color:CalColor = coreMaterial.getAmbientColor()
	
		' write it to the color buffer
		colorBuffer[0] = color.red
		colorBuffer[1] = color.green
		colorBuffer[2] = color.blue
		colorBuffer[3] = color.alpha

	End


	Method getDiffuseColor:Void(colorBuffer:Float[])
	
		' get the core material
		Local coreMaterial:CalCoreMaterial = this.m_model.getCoreModel().getCoreMaterial(this.m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null then
			' write default values to the color buffer
			colorBuffer[0] = 192
			colorBuffer[1] = 192
			colorBuffer[2] = 192
			colorBuffer[3] = 192
	
			return
		Endif
	
		' get the ambient color of the material
		Local color:CalColor = coreMaterial.getDiffuseColor()
	
		' write it to the color buffer
		colorBuffer[0] = color.red
		colorBuffer[1] = color.green
		colorBuffer[2] = color.blue
		colorBuffer[3] = color.alpha

	End
	
	Method getFaceCount:Int()
		Return m_selectedSubmesh.getFaceCount()
	End
	
	Method getFaces:Int(faceBuffer:Int[])
		Return m_selectedSubmesh.getFaces(faceBuffer)
	End
	
	Method getMapCount:Int()
		' get the core material
		Local coreMaterial:CalCoreMaterial = m_model.getCoreModel().getCoreMaterial(m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null Then
			Return 0
		Endif
		Return coreMaterial.getMapCount()	
	End
	
	Method getMapUserData:Object(mapId:Int)
		' get the core material
		Local coreMaterial:CalCoreMaterial = m_model.getCoreModel().getCoreMaterial(m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null Then
			Return Null
		Endif
		' get the map vector
		Local vectorMap:CalMap[] = coreMaterial.getVectorMap()
	
		' check if the map id is valid
		If mapId < 0 Or mapId >= vectorMap.Length then
			Print "Invalid Map ID"
			Return Null
		Endif
	
		Return vectorMap[mapId].userData		
	End
	
	Method getMeshCount:Int()
		' get the attached meshes vector
		Local vectorMesh:CalMesh[] = m_model.getVectorMesh()
		Return vectorMesh.Length	
	End
	
	Method getNormals:Int(normalBuffer:Float[], stride:Int=3)
		
		' check if the submesh handles vertex data internally
		If m_selectedSubmesh.hasInternalData() = True then
			' get the normal vector of the submesh
			Local vectorNormal:CalVector[] = m_selectedSubmesh.getVectorNormal()
	
			' get the number of normals (= number of vertices) in the submesh
			Local normalCount:Int = m_selectedSubmesh.getVertexCount()
	

			If stride <= 0 Then
				stride = 3
			Endif
			Local j:Int = 0
			For Local i:Int = 0 To normalCount-1
				Local normal:CalVector = vectorNormal[i]
				normalBuffer[j    ] = normal.x
				normalBuffer[j + 1] = normal.y
				normalBuffer[j + 2] = normal.z
				j+=stride
			Next
	
			Return normalCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		Return m_model.getPhysique().calculateNormals(m_selectedSubmesh, normalBuffer, stride)	
	
	End
	
	Method getShininess:Float()
		' get the core material
		Local coreMaterial:CalCoreMaterial = m_model.getCoreModel().getCoreMaterial(m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null Then
			Return 50
		Endif
		Return coreMaterial.getShininess()		
	End
	
	Method getSpecularColor:Void(colorBuffer:Float[])
	
		' get the core material
		Local coreMaterial:CalCoreMaterial = this.m_model.getCoreModel().getCoreMaterial(this.m_selectedSubmesh.getCoreMaterialId())
		If coreMaterial = Null then
			' write default values to the color buffer
			colorBuffer[0] = 255
			colorBuffer[1] = 255
			colorBuffer[2] = 255
			colorBuffer[3] = 0
	
			Return
		Endif
	
		' get the ambient color of the material
		Local color:CalColor = coreMaterial.getSpecularColor()
	
		' write it to the color buffer
		colorBuffer[0] = color.red
		colorBuffer[1] = color.green
		colorBuffer[2] = color.blue
		colorBuffer[3] = color.alpha

	End
	
	Method getSubmeshCount:Int(meshId:Int)
		' get the attached meshes vector
		Local vectorMesh:CalMesh[] = m_model.getVectorMesh()
	
		' check if the mesh id is valid
		If meshId < 0 Or meshId >= vectorMesh.Length then
			Print "Invalid Mesh ID"
			return 0
		Endif
	
		Return vectorMesh[meshId].getSubmeshCount()	
	End
	
	Method getTextureCoordinates:Int(mapId:Int, textureCoordinateBuffer:Float[], stride:Int=2)
	
		' get the texture coordinate vector vector
		Local vectorvectorTextureCoordinate:CalTextureCoordinate[][] = m_selectedSubmesh.getCoreSubmesh().getVectorVectorTextureCoordinate()
	
		' check if the map id is valid
		If mapId < 0 Or mapId >= vectorvectorTextureCoordinate.Length then
			Print "Map ID is invalid"
			return -1
		Endif
	
		' get the number of texture coordinates to return
		Local textureCoordinateCount:Int = m_selectedSubmesh.getVertexCount()
	

		If stride <= 0 Then
			stride = 2
		Endif
		Local j:Int = 0
		For Local i:Int = 0  To textureCoordinateCount-1
			Local texCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[mapId][i]
			textureCoordinateBuffer[j    ] = texCoord.u
			textureCoordinateBuffer[j + 1] = texCoord.v
			j+=stride
		Next
	
		Return textureCoordinateCount	
	
	End
	
	Method getVertexCount:Int()
		Return m_selectedSubmesh.getVertexCount()
	End
	
	Method getVertices:Int(vertexBuffer:Float[], stride:Int=3)
		
		' check if the submesh handles vertex data internally
		If m_selectedSubmesh.hasInternalData() = True then
			' get the vertex vector of the submesh
			Local vectorVertex:CalVector[] = m_selectedSubmesh.getVectorVertex()
	
			' get the number of vertices in the submesh
			Local vertexCount:Int = m_selectedSubmesh.getVertexCount()
	
			' copy the internal vertex data into the provided vertex buffer
	
			If stride <= 0 Then
				stride = 3
			Endif
			Local j:Int=0
			For Local i:Int = 0 To vertexCount-1
				Local vertex:CalVector = vectorVertex[i]
				vertexBuffer[j    ] = vertex.x
				vertexBuffer[j + 1] = vertex.y
				vertexBuffer[j + 2] = vertex.z
				j+=stride
			Next
	
			Return vertexCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		Return m_model.getPhysique().calculateVertices(m_selectedSubmesh, vertexBuffer, stride)		
		
	End
	
	Method getTangentSpaces:Int(mapId:Int, tangentSpaceBuffer:Float[], stride:Int=4)
		' get the texture coordinate vector vector
		Local vectorvectorTangentSpace:CalTangentSpace[] = m_selectedSubmesh.getCoreSubmesh().getVectorVectorTangentSpace()
	
		' check if the map id is valid
		If mapId < 0 Or mapId >= vectorvectorTangentSpace.Length Or  m_selectedSubmesh.isTangentsEnabled(mapId) = False
			Print "Invalid Map ID or Tangents Not Enabled!"
			Return -1
		Endif
	
		' check if the submesh handles vertex data internally
		If m_selectedSubmesh.hasInternalData() = True Then
			' get the normal vector of the submesh
			Local vectorTangentSpace:CalTangentSpace[] = m_selectedSubmesh.getVectorVectorTangentSpace()[mapId]
	
			' get the number of normals (= number of vertices) in the submesh
			Local tangentSpaceCount:Int = m_selectedSubmesh.getVertexCount()
	
			If stride <= 0 Then
				stride = 4
			Endif
			Local j:Int = 0
			For Local i:Int = 0 To tangentSpaceCount-1
				Local tangentSpace = vectorTangentSpace[i]
				Local tangent = tangentSpace.tangent
				tangentSpaceBuffer[j    ] = tangent.x
				tangentSpaceBuffer[j + 1] = tangent.y
				tangentSpaceBuffer[j + 2] = tangent.z
				tangentSpaceBuffer[j + 3] = tangentSpace.crossFactor
				j+=stride
			Next
	
			Return tangentSpaceCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		return m_model.getPhysique().calculateTangentSpaces(m_selectedSubmesh, mapId, tangentSpaceBuffer, stride)		
	End
	
	Method getVerticesAndNormals:Int(vertexBuffer:Float[], stride:Int=6)
		' check if the submesh handles vertex data internally
		If m_selectedSubmesh.hasInternalData() = True then
			' get the vertex vector of the submesh
			Local vectorVertex:CalVector[] = m_selectedSubmesh.getVectorVertex()
			' get the normal vector of the submesh
			Local vectorNormal:CalVector[] = m_selectedSubmesh.getVectorNormal()
	
			' get the number of vertices in the submesh
			Local vertexCount:Int = m_selectedSubmesh.getVertexCount()
	

			If stride <= 0 Then
				stride = 6
			Endif
			Local j:Int=0
			For Local i:Int = 0 To vertexCount-1
				Local vertex:CalVector = vectorVertex[i]
				Local normal:CalVector = vectorNormal[i]
				vertexBuffer[j    ] = vertex.x
				vertexBuffer[j + 1] = vertex.y
				vertexBuffer[j + 2] = vertex.z
				vertexBuffer[j + 3] = normal.x
				vertexBuffer[j + 4] = normal.y
				vertexBuffer[j + 5] = normal.z
				j+=stride
			Next
	
			Return vertexCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		Return m_model.getPhysique().calculateVerticesAndNormals(m_selectedSubmesh, vertexBuffer, stride)		
	End
	
	
	Method getVerticesNormalsAndTexCoords:Int(vertexBuffer:Float[], numTexCoords:Int=1)
	
		' check if the submesh handles vertex data internally
		If m_selectedSubmesh.hasInternalData() = True Then
			' get the vertex vector of the submesh
			Local vectorVertex:CalVector[] = m_selectedSubmesh.getVectorVertex()
			' get the normal vector of the submesh
			Local vectorNormal:CalVector[] = m_selectedSubmesh.getVectorNormal()	
			' get the texture coordinate vector vector
			Local vectorvectorTextureCoordinate:CalTextureCoordinate[][] = m_selectedSubmesh.getCoreSubmesh().getVectorVectorTextureCoordinate()
	
			Local textureCoordinateCount:Int = vectorvectorTextureCoordinate.Length
	
			If numTexCoords < 0 Then
				numTexCoords = 1
			Endif
			' check if the given texture coordinate count is valid
			If numTexCoords < 0 Or numTexCoords > textureCoordinateCount Then
				If textureCoordinateCount <> 0 then
					Print "Invalid Texture Coord Count"
					Return -1
				Endif
			Endif
	
			' get the number of vertices in the submesh
			Local vertexCount:Int = m_selectedSubmesh.getVertexCount()
	
	
			If textureCoordinateCount = 0 then
				Local vi:Int = 0
				For Local vertexId:Int = 0 To vertexCount-1
					Local vertex:CalVector = vectorVertex[vertexId]
					Local normal:CalVector = vectorNormal[vertexId]
					vertexBuffer[vi    ] = vertex.x
					vertexBuffer[vi + 1] = vertex.y
					vertexBuffer[vi + 2] = vertex.z
					vertexBuffer[vi + 3] = normal.x
					vertexBuffer[vi + 4] = normal.y
					vertexBuffer[vi + 5] = normal.z
					vi += 6 + numTexCoords * 2
				Next
			Else
				If numTexCoords = 1 Then
					Local vi:Int = 0
					For Local vertexId:Int = 0 To vertexCount-1
						Local vertex:CalVector= vectorVertex[vertexId]
						Local normal:CalVector = vectorNormal[vertexId]
						Local texCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[0][vertexId]
						vertexBuffer[vi    ] = vertex.x
						vertexBuffer[vi + 1] = vertex.y
						vertexBuffer[vi + 2] = vertex.z
						vertexBuffer[vi + 3] = normal.x
						vertexBuffer[vi + 4] = normal.y
						vertexBuffer[vi + 5] = normal.z
						vertexBuffer[vi + 6] = texCoord.u
						vertexBuffer[vi + 7] = texCoord.v
						vi += 8
					Next
				Else
					Local vi:Int = 0
					For Local vertexId:Int = 0 To vertexCount-1
						Local vertex:CalVector = vectorVertex[vertexId]
						Local normal:CalVector = vectorNormal[vertexId]
						vertexBuffer[vi    ] = vertex.x
						vertexBuffer[vi + 1] = vertex.y
						vertexBuffer[vi + 2] = vertex.z
						vertexBuffer[vi + 3] = normal.x
						vertexBuffer[vi + 4] = normal.y
						vertexBuffer[vi + 5] = normal.z
						vi += 6
	
						For Local mapId:Int = 0 To numTexCoords-1
							Local texCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[mapId][vertexId]
							vertexBuffer[vi    ] = texCoord.u
							vertexBuffer[vi + 1] = texCoord.v
							vi += 2
						Next
					Next
				Endif		
			Endif
	
			Return vertexCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		Return m_model.getPhysique().calculateVerticesNormalsAndTexCoords(m_selectedSubmesh, vertexBuffer, numTexCoords)	
	
	End
	
	Method isTangentsEnabled:Bool(mapId:Int)
		Return m_selectedSubmesh.isTangentsEnabled(mapId)
	End
	
	Method selectMeshSubmesh:Bool(meshId:Int, submeshId:Int)
	
		' get the attached meshes vector
		Local vectorMesh:CalMesh[] = m_model.getVectorMesh()
	
		' check if the mesh id is valid
		If meshId < 0 Or meshId >= vectorMesh.Length then
			Print "Invalid Mesh ID"
			Return False
		Endif
	
		' get the core submesh
		m_selectedSubmesh = vectorMesh[meshId].getSubmesh(submeshId)
		If m_selectedSubmesh = Null Then
			Return False
		Endif
		
		Return True	
	
	End
	
	Method setNormalization:Void(normalize:Bool)
		m_model.getPhysique().setNormalization(normalize)
	End
	
End Class